'''

生产者与消费者， 两个线程之间的通信

Python的queue模块中提供了同步的线程安全的队列类

包括FIFO先进先出队列Queue LIFO后入先出队列LifoQueue和优先级队列PriorityQueue
这些队列都实现了锁源语（可以理解为原子操作即要么不做 要么做完）能够在多线程中直接使用
可以使用队列来实现线程间的同步


线程：
Thread
1. 创建线程
    A. t=Thread(target=..,name=..) 新建
       t.start 就绪
            run()
       join() 让主线程让步
    B. 自定义线程
        class MyThread(Thread)
            def run(self):
                pass
       t = MyThread()
       t.start()

2. 数据共享
    进程共享数据和线程共享数据的区别
    进程是每个进程中都有一份
    线程是共同一个数据 -》数据安全性问题

    GIL ---》python是伪线程
    lock =Lock()
    lock.acquire() 获取锁
        ....
    lock.release() 释放锁

    ----只要用锁： 死锁
    避免死锁

3. 线程间通信  生产者与消费者
    生产者
    消费者
    from queue import Queue
    q = Queue(10)
    t1 = Thread(name='生产者', target=producer, args=(q,))
    t2 = Thread(name='消费者', target=consumer, args=(q,))

    t1.start()
    t2.start()

    t1.join()
    t2.join()
'''
import random
from threading import Thread
from queue import Queue
from time import sleep


def producer(q):
    assert isinstance(q, Queue)
    for i in range(10):
        ran = random.randint(1, 10)
        q.put('----------->生产者生产了:' + str(ran))
        print('生产者生产了:', ran)
        sleep(1)

    q.put(None)
    # 完成
    q.task_done()


def consumer(q):
    assert isinstance(q, Queue)
    while True:
        res = q.get()
        if res is None:
            print("消费完毕")
            break
        print(res)
        sleep(4)

    q.task_done()


if __name__ == '__main__':
    q = Queue(10)
    t1 = Thread(name='生产者', target=producer, args=(q,))
    t2 = Thread(name='消费者', target=consumer, args=(q,))

    t1.start()
    t2.start()

    t1.join()
    t2.join()

    print('END')
